﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfControlLibrary4MVVMLib
{
    public class UndoManager
    {
        readonly List<IUndoCommand> _undoList, _redoList;

        public UndoManager(int limit = 0)
        {
            if (limit < 0)
                throw new ArgumentException("undo limit must be a positive integer", "limit");
            UndoLimit = limit;
            _undoList = new List<IUndoCommand>(limit > 0 ? limit : 16);
            _redoList = new List<IUndoCommand>(limit > 0 ? limit : 16);
        }

        public int UndoLimit { get; private set; }

        public virtual bool CanUndo
        {
            get { return _undoList.Count > 0; }
        }

        public virtual void Undo()
        {
            if (!CanUndo)
                throw new InvalidOperationException("cannot undo");
            int index = _undoList.Count - 1;
            var cmd = _undoList[index];
            cmd.Undo();
            _undoList.RemoveAt(index);
            _redoList.Add(cmd);
        }

        public virtual bool CanRedo
        {
            get { return _redoList.Count > 0; }
        }

        public virtual void Redo()
        {
            if (!CanRedo)
                throw new InvalidOperationException("cannot redo");
            int index = _redoList.Count - 1;
            var cmd = _redoList[index];
            cmd.Execute(null);
            _redoList.RemoveAt(index);
            _undoList.Add(cmd);
        }

        public void AddCommand(IUndoCommand cmd)
        {
            _undoList.Add(cmd);
            _redoList.Clear();
            if (UndoLimit > 0 && _undoList.Count > UndoLimit)
                _undoList.RemoveAt(0);
        }
    }
}
